package dxf;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class NIODemo {

    private static Selector selector;

    public static void main(String[] args) throws IOException {

         selector = Selector.open();//打开选择器

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//打开通道

        serverSocketChannel.configureBlocking(false);

        ServerSocket serverSocket = serverSocketChannel.socket();

        serverSocket.bind(new InetSocketAddress(8081));


        SelectionKey myId = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int keyCount = selector.select(); //开始轮训
            System.out.println("当前有:" + keyCount + "channel有事件就绪");
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            SelectionKey key = null;
            while (iterator.hasNext()) {
                key = iterator.next();
                iterator.remove();

                process(key);
            }
        }

    }


    private static void process(SelectionKey key) throws IOException {
        //该channel已就绪，可接收消息
        if (key.isAcceptable()) {
            System.out.println("accept事件就绪...");
            doAccept(key);
        } else if (key.isReadable()) {
            System.out.println("read事件就绪...");
            doRead(key);
        } else if (key.isWritable()) {
            System.out.println("write事件就绪...");
            doWrite(key);
        }
    }



    private static void doWrite(SelectionKey key) throws IOException {
        //获取对应的socket
        SocketChannel socket = (SocketChannel)key.channel();
        //获取key上的附件
        String content = (String)key.attachment();
        socket.write(ByteBuffer.wrap(content.getBytes()));
        socket.close();
    }

    private static void doRead(SelectionKey key) throws IOException {
        //获取对应的socket
        SocketChannel socket = (SocketChannel)key.channel();
        //设置一个读取数据的Buffer 大小为1024
        ByteBuffer buff = ByteBuffer.allocate(1024);
        StringBuilder content = new StringBuilder();

        while(socket.read(buff) > 0) {
            buff.flip();
            content.append(new String(buff.array(),"utf-8"));
        }
        //注册selector，并设置为可写模式
        key = socket.register(selector,SelectionKey.OP_WRITE);
        //在key上携带一个附件(附近就是之后要写的内容)
        key.attach("服务端已收到:"+content);
        System.out.println("读取内容：" + content);
    }

    private  static void doAccept(SelectionKey key) throws IOException {
        //获取对应的channel
        ServerSocketChannel server = (ServerSocketChannel)key.channel();
        //从channel中获取socket信息
        SocketChannel socket = server.accept();
        //设置为非阻塞模式
        socket.configureBlocking(false);
        //注册selector，并设置为可读模式
        socket.register(selector, SelectionKey.OP_READ);
    }



}
